package ru.nsu.fit.iconveyor.engine;

import ru.nsu.fit.iconveyor.conveyor.Conveyor;

public interface Engine {
    /**
     * Sets conveyor to be executed in the engine.
     * @param conveyor
     */
    void setConveyor(Conveyor conveyor);

    /**
     * Starts execution of conveyor. This method returns immediately, conveyor is executed in separate thread(s).
     * @throws IllegalStateException if conveyor was not set or execution is already started or finished.
     */
    void start();

    /**
     * Force stopping execution of conveyor.
     */
    void stop();

    /**
     * Returns state of conveyor.
     * @return state of conveyor.
     */
    State getState();

    /**
     * Adds EngineStateObserver
     * @param observer
     */
    void addEngineStateObserver(EngineStateObserver observer);

    /**
     * Removes EngineStateObserver
     * @param observer
     */
    void removeEngineStateObserver(EngineStateObserver observer);

    /**
     * Adds ConveyorExecutionObserver
     * @param observer
     */
    void addConveyorExecutionObserver(ConveyorExecutionObserver observer);

    /**
     * Removes ConveyorExecutionObserver
     * @param observer
     */
    void removeConveyorExecutionObserver(ConveyorExecutionObserver observer);

    static enum State {
        /** Execution of conveyor not started. */
        NOT_STARTED,

        /** Conveyor is being executed. */
        RUNNING,

        /** Execution of conveyor successfully finished. */
        FINISHED,

        /** Execution of conveyor was force stopped. */
        STOPPED,

        /** Execution of conveyor failed because of some exception. */
        FAILED
    }

}
